// @Describe: 设备管理模块
package core

import (
	"context"
	"errors"
	"github.com/rs/zerolog/log"
	"sort"
	"time"
	"wormhole/constant"
	"wormhole/protos/hole"
)

// GetDeviceByIp
//  @Description: 通过Ip获取服务端管理的设备信息
//  @receiver s
//  @param ip
//  @return *hole.Device
func (s *holeServer) GetDeviceByIp(ip string) *hole.Device {
	if device, ok := s.IpMap[ip]; ok {
		return device
	} else {
		return nil
	}
}

// GetDeviceByName
//  @Description: 通过名称获取服务端管理的设备信息
//  @receiver s
//  @param name
//  @return *hole.Device
func (s *holeServer) GetDeviceByName(name string) *hole.Device {
	if device, ok := s.NameMap[name]; ok {
		return device
	} else {
		return nil
	}
}
func (s *holeServer) GetDevice(ctx context.Context, key *hole.DeviceKey) (*hole.Device, error) {
	log.Trace().Interface("key", key).Send()
	if key.Ripple.Name != "" {
		deviceP, ok := s.NameMap[key.Ripple.Name]
		if ok {
			log.Debug().Interface("device", deviceP).Send()
			return deviceP, nil
		}
	} else if key.Ripple.Ip != "" {
		deviceP, ok := s.IpMap[key.Ripple.Ip]
		if ok {
			log.Debug().Interface("device", deviceP).Send()
			return deviceP, nil
		}
	} else {
		deviceP, ok := s.IndexMap[int(key.Index)]
		if ok {
			log.Debug().Interface("device", deviceP).Send()
			return deviceP, nil
		}
	}
	log.Debug().Msg("cannot find device")
	return nil, errors.New("cannot find device")
}

func (s *holeServer) OnlineDevice(Ripple *hole.Ripple) {
	if deviceP, ok := s.IpMap[Ripple.Ip]; ok {
		deviceP.Key.Ripple = Ripple
		deviceP.StateCode = 1
		deviceP.LastActiveTime = time.Now().Format(time.RFC3339)
	} else {
		key := &hole.DeviceKey{
			Ripple: Ripple,
			Index:  int32(s.CurrentIndex),
		}
		deviceP = &hole.Device{
			Key:            key,
			StateCode:      1,
			LastActiveTime: time.Now().Format(constant.DefaultTimeFormat),
		}
		s.IndexMap[s.CurrentIndex] = deviceP
		s.CurrentIndex++
		s.NameMap[Ripple.Name] = deviceP
		s.IpMap[Ripple.Ip] = deviceP
	}
}

func (s *holeServer) OfflineDevice(Ripple *hole.Ripple) {
	if deviceP, ok := s.IpMap[Ripple.Ip]; ok {
		deviceP.StateCode = 0
	}
}

func (s *holeServer) CheckHealth(ctx context.Context, empty *hole.Empty) (*hole.Reply, error) {
	return new(hole.Reply), nil
}

func (s *holeServer) ListDevice(ctx context.Context, e *hole.Empty) (*hole.DeviceListResponse, error) {
	devices := make([]*hole.Device, 0)
	for _, v := range s.IpMap {
		devices = append(devices, v)
	}
	sort.Slice(devices, func(i, j int) bool {
		return devices[i].Key.Index < devices[j].Key.Index
	})
	response := &hole.DeviceListResponse{
		Devices: devices,
	}
	return response, nil
}

func (s *holeServer) FillDeviceKey(key *hole.DeviceKey) bool {
	if key.Ripple.Ip != "" && key.Ripple.Port != 0 {
		return true
	}

	device, err := s.GetDevice(context.Background(), key)
	if err != nil {
		log.Err(err).Msg("无法找到指定设备!")
		return false
	}
	if device.StateCode == 0 {
		log.Error().Msg("指定设备离线,无法接收!")
		return false
	}
	key.Ripple = device.Key.Ripple
	return true
}
